package com.mahjong.server.component.logic.main;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.mahjong.server.component.logic.manager.CacheManager;
import com.mahjong.server.component.logic.util.ArrayUtil;
import com.mahjong.server.component.logic.util.DataUtil;
import com.mahjong.server.component.logic.util.LogicConstant;


/**
 * 麻将主要动作：吃、碰、杠、发牌、补花等
 * @user:   Administrator
 * @author： 游刚
 * @version：1.0
 * @created：Apr 9, 2013
 */

public class KHMahjongAction {

	/**
	 * 生成牌，一次生成number张
	 *  生成的牌绑定到玩家对象中
	 * <p>从一副麻将中取,取出后则麻将中相应减少
	 * @param roomId 房间id
	 * @param number
	 * @param isSort 是否排序 默认true
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public String[] createPai(int roomId,int number,boolean isSort) {
		String[] pais = new String[number];
		//缓存中当前房间的信息
		Map map = (Map)CacheManager.getCache(roomId+"");
		String[] allPai = (String[])map.get(LogicConstant.Left_MAHJONG_2);
		for(int i = 0;i <pais.length; i++) {
			int index = DataUtil.randomNum(allPai.length);
			String pai = ArrayUtil.getElement(allPai, index);
			allPai = ArrayUtil.removeElement(allPai, index);
			pais[i]=pai;
		}
		if (isSort) {
			pais = KHMahjongLogic.sortPai(pais);
		}
		//把当局剩余的牌重新放到缓存中
		map.put(LogicConstant.Left_MAHJONG_2, allPai);
		CacheManager.setCache(roomId+"", map);
		return pais;
	}
	
	/**
	 * 牌局开始时生成玩家牌,每次生成4张
	 * @param roomId 房间id
	 * @param isSort 是否排序 默认true
	 * @return
	 */
	public String[] createPai(int roomId,boolean isSort) {
		return createPai(roomId, 4, isSort);
	}
	
	public String[] createPai(int roomId) {
		return createPai(roomId, 4, true);
	}
	
	/**
	 * 牌局开始时一次性生成玩家手中的牌,生成12张
	 * @param roomId 房间id
	 * @param isSort 是否排序 默认true
	 * @return
	 */
	public String[] createPai12(int roomId,boolean isSort) {
		return createPai(roomId, 12, isSort);
	}
	
	public String[] createPai12(int roomId) {
		return createPai(roomId, 12, true);
	}
	
	/**
	 * 补花:从剩余麻将中取出一张牌
	 * @param roomId
	 * @return
	 */
	public String buHua(int roomId) {
		return createPai(roomId, 1, true)[0];
	}

	/**
	 * 吃(有多种选择时,由玩家选择用哪两张来吃)
	 * @param pais 玩家手中的牌
	 * @param upai1 玩家手中用来吃的牌1
	 * @param upai2 玩家手中用来吃的牌2
	 * @return 玩家手中剩余的牌
	 */
	public String[] chi(String[] pais,String upai1,String upai2) {
		return ArrayUtil.removeElement(pais, upai1,upai2);
	}
	
	/**
	 * 吃
	 * <p>若只有一种吃法：执行顺序 isChi()-客户端选择后-此方法</p>
	 * <p>若有多种吃法：  执行顺序 isChi()-客户端选择后-此方法-客户端选择后-chi(String[] pais,String upai1,String upai2)</p>
	 * @param pai 打出的牌子
	 * @param pais 当前玩家手中的牌,注意是排序后的
	 * @return 
	 *          key-used 执行操作使用掉的牌(数组),有多种吃法时为null
	 *          key-left 玩家手中还剩下的牌(数组)
	 *          key-item 每种吃法需要用掉的牌 数组依次放入(格式如["筒2_4;筒2_3","筒5_4;筒6_1"]),只有一种吃法时为null
	 */
	@SuppressWarnings("unchecked")
  public Map chi(String pai,String[] pais) {
		Map<String,String[]> result = new HashMap<String,String[]>();
		List<String> chiList = new ArrayList<String>();
		List<String> usedList = new ArrayList<String>();//各种吃法所用掉的牌
		List<String> removeList = new ArrayList<String>();//每吃一次移除一张牌子的集合
		
		//前缀 萬9_4 --> 萬9
		String paiPrefix = pai.split("_")[0];
		// 萬9_4 --> 9
		Integer paiIndex = Integer.parseInt(paiPrefix.substring(1,2)); //4
		List<Integer> list = new ArrayList<Integer>();
		//把同一类,并且能靠着的牌找出来
		int i = 0;
		for(String p : pais) {
			if (p.indexOf("东")!=-1
					|| p.indexOf("南")!=-1
					|| p.indexOf("西")!=-1
					|| p.indexOf("北")!=-1
					|| p.indexOf("中")!=-1
					|| p.indexOf("發")!=-1
					|| p.indexOf("白")!=-1) {
				continue;
			}
			i = Integer.parseInt(p.split("_")[0].substring(1,2));
			if (p.substring(0,1).equals(paiPrefix.substring(0,1))
					&&  (i+2 >= paiIndex && i-2 <= paiIndex)) {
			    list.add(i);
			    chiList.add(p);
		    }
		}

		String[] usedPais = chi(list,chiList,paiIndex);
		while(usedPais!=null) {
			if (usedList.contains(usedPais[0]) && usedList.contains(usedPais[1])) {
			} else {
				usedList.add(usedPais[0]);//添加到所用掉的牌集合中
				usedList.add(usedPais[1]);
			}
			removeList.add(usedPais[0]);
			chiList.remove(usedPais[0]);//把同一类牌中吃掉的元素去掉
			//chiList.remove(usedPais[1]);
			list = new ArrayList<Integer>();
			for(String p : chiList) {
				i = Integer.parseInt(p.split("_")[0].substring(1,2));
				if ( !removeList.contains(p)) {
				    list.add(i);
			    }
			}
			
			usedPais = null;
			if (chiList!=null && chiList.size()>=2) {
				usedPais = chi(list,chiList,paiIndex);
			}
		}
		
		//输出去重前的各种吃法组合
		//for(String s : usedList) {
			//System.out.println(s);
		//}
		
		String[] usedPai = null;
		if (usedList.size()>2) {//多种吃法
			//去除重复组合
			Map<String,String> group = new HashMap<String,String>();
			for (int j = 0; j < usedList.size(); j++) {
				if (j%2==1) {
					group.put(usedList.get(j-1).split("_")[0]+usedList.get(j).split("_")[0], 
							usedList.get(j-1)+";"+usedList.get(j));//例如key：萬5萬6  value：萬5_3;萬6_3
				}
			}
			result.put("used", null);
			result.put("left", pais);
			usedPai = new String[group.keySet().size()];
			int k = 0;
			Iterator iter = group.keySet().iterator();
			while(iter.hasNext()) {
				usedPai[k] = group.get(iter.next().toString());
				k++;
			}
			result.put("item", usedPai);
			
		} else {//只有一种吃法
			usedPai = new String[]{usedList.get(0),usedList.get(1)};
			result.put("used", usedPai);
			result.put("left", ArrayUtil.removeElement(pais, usedPai));
			result.put("item", null);
		}

        return result;
	}
	
	private String[] chi(List<Integer> list,List<String> chiList,Integer paiIndex ) {
		String[] usedPais = null;
		for (int i = 0; i < list.size(); i++) {
			if (i+1>=list.size()) { //保证以下list.get(i+1) 不会数组越界
				continue;
			}
			if ((paiIndex-2==list.get(i) && paiIndex-1==list.get(i+1))
					|| (paiIndex-1==list.get(i) && paiIndex+1==list.get(i+1))
					|| (paiIndex+1==list.get(i) && paiIndex+2==list.get(i+1))) {
				if (chiList.get(i).split("_")[0].equals(chiList.get(i+1).split("_")[0])) {
					continue;
				}
				usedPais = new String[2];
				usedPais[0] = chiList.get(i);
				usedPais[1] = chiList.get(i+1);
				return usedPais;
			}
		}
		return usedPais;
	}
	
	/**
	 * 碰
	 * @param pai 打出的牌
	 * @param pais 玩家手中的牌
	 * return 玩家手中剩余的牌
	 */
	public String[] peng(String pai,String[] pais) {
		String[] left = new String[pais.length-2];
		int index = 0;
		for(String p : pais) {
			if (!p.split("_")[0].equals(pai.split("_")[0])) { //不是同一类牌
				left[index] = p;
				index++;
			}
		}
		return left;
	}
	
	/**
	 * 杠
	 * @param pai 打出的牌
	 * @param pais 玩家手中的牌
	 * return 玩家手中剩余的牌
	 */
	public String[] gang(String pai,String[] pais) {
		String[] left = new String[pais.length-3];
		int index = 0;
		for(String p : pais) {
			if (!p.split("_")[0].equals(pai.split("_")[0])) { //不是同一类牌
				left[index] = p;
				index++;
			}
		}
		return left;
	}
	
}
